package com.yvon.service.demo.algorithm.offer;

/**
 * 顺时针打印矩阵
 * 输入一个矩阵，按照从外向里以顺时针的顺序依次打印出每一个数字。
 * https://doocs.gitee.io/leetcode/#/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9829.%20%E9%A1%BA%E6%97%B6%E9%92%88%E6%89%93%E5%8D%B0%E7%9F%A9%E9%98%B5/README
 */
public class P29 {

    public static void main(String[] args) {
        int[][] matrix = new int[][]{{1, 2, 3, 4}};
        for(int i = 0; i < matrix.length; i++){
            for(int j = 0; j < matrix[0].length; j++){
                System.out.print(matrix[i][j] + "      ");
            }
            System.out.println();
        }
        Solution solution = new P29().new Solution();
        int[] array = solution.spiralOrder(matrix);
        // 进行打印结果进行测试
        for (int i = 0; i < array.length; i++) {
            if(i == array.length-1){
                System.out.print(array[i]);
            } else {
                System.out.print(array[i] + ",");
            }
        }
    }

    class Solution {

        /**
         * 1.空值处理：当matrix为空时，直接返回空数组
         * 2.初始化：
         *      矩阵左边、右边、上边、下边: left、right、top、bottom四个边界
         *      用于打印的结果列表：res
         * 3.循环打印：
         *   从左到右、从上到下、从右往左、从下往上四个方向循环，每个方向做以下三件事
         *   1.根据边界打印，即将元素按顺序添加到res尾部
         *   2.边界向内收缩1(代表已被打印完毕)
         *   3.判断是否打印完毕(边界相遇),若打印完毕则挑出
         *
         * 4.返回值：返回res即可
         * 打印方向 1. 根据边界打印 2. 边界向内收缩 3. 是否打印完毕
         * 从左向右 左边界l ，右边界 r 上边界 t 加 1 是否 t > b
         * 从上向下 上边界 t ，下边界b 右边界 r 减 1 是否 l > r
         * 从右向左 右边界 r ，左边界l 下边界 b 减 1 是否 t > b
         * 从下向上 下边界 b ，上边界t 左边界 l 加 1 是否 l > r
         *
         * https://blog.csdn.net/qq_43751200/article/details/114375858?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-1-114375858-blog-73196047.pc_relevant_multi_platform_whitelistv1&spm=1001.2101.3001.4242.2&utm_relevant_index=4
         */
        public  int[] spiralOrder(int[][] matrix) {  // 必须要是静态的才可以在主函数中使用
            if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
                return new int[0];
            }
            // 左边
            int left = 0;
            // 右边
            int right = matrix[0].length - 1;
            // 上边
            int top = 0;
            // 下边
            int bottom = matrix.length -1;
            int x= 0;
            int[] res = new int[(right + 1) * (bottom + 1)];
            while (true) {
                for (int i = left; i <= right; i++) {
                    res[x++] = matrix[top][i];
                }
                if (++top > bottom) {
                    break;
                }
                for (int i = top; i <= bottom; i++) {
                    res[x++] = matrix[i][right];
                }
                if (left > --right) {
                    break;
                }
                for (int i = right; i >= left; i--) {
                    res[x++] = matrix[bottom][i];
                }
                if (top > --bottom) {
                    break;
                }
                for (int i = bottom; i >= top; i--) {
                    res[x++] = matrix[i][left];
                }
                if (++left> right) {
                    break;
                }


            }
            return res;

        }
    }
}
